package mcps

import (
	"bufio"
	"context"
	"fmt"
	"github.com/mark3labs/mcp-go/mcp"
	"github.com/mark3labs/mcp-go/server"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

func LogMCPServer() {
	s := server.NewMCPServer(
		"日志分析工具",
		"1.0.0",
	)

	// 添加日志读取工具
	logReadTool := mcp.NewTool("log_read",
		mcp.WithDescription("读取指定日志文件的内容"),
		mcp.WithString("file_path",
			mcp.Required(),
			mcp.Description("日志文件路径"),
		),
		mcp.WithString("filter",
			mcp.Description("过滤关键字"),
		),
		mcp.WithString("tail_lines",
			mcp.Description("读取最后N行，默认全部读取"),
		),
	)

	// 添加日志搜索工具
	logSearchTool := mcp.NewTool("log_search",
		mcp.WithDescription("在日志目录中搜索指定内容"),
		mcp.WithString("dir_path",
			mcp.Required(),
			mcp.Description("日志目录路径"),
		),
		mcp.WithString("keyword",
			mcp.Required(),
			mcp.Description("搜索关键字"),
		),
		mcp.WithString("file_pattern",
			mcp.Description("文件名匹配模式（如：*.log）"),
		),
	)

	// 添加日志监控工具
	logMonitorTool := mcp.NewTool("log_monitor",
		mcp.WithDescription("实时监控日志文件变化"),
		mcp.WithString("file_path",
			mcp.Required(),
			mcp.Description("日志文件路径"),
		),
		mcp.WithString("duration",
			mcp.Description("监控持续时间（如：30s, 1m, 5m），默认为1分钟"),
		),
	)

	// 添加工具处理函数
	s.AddTool(logReadTool, logReadHandler)
	s.AddTool(logSearchTool, logSearchHandler)
	s.AddTool(logMonitorTool, logMonitorHandler)

	// 启动服务器
	fmt.Println("日志分析服务已启动...")
	if err := server.ServeStdio(s); err != nil {
		fmt.Printf("服务器错误: %v\n", err)
	}
}

func logReadHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	// 获取文件路径
	filePath, ok := request.Params.Arguments["file_path"].(string)
	if !ok || filePath == "" {
		return mcp.NewToolResultError("file_path 参数必须是非空字符串"), nil
	}

	// 获取过滤关键字
	filter, _ := request.Params.Arguments["filter"].(string)

	// 获取尾行数
	tailLines := -1 // 默认读取全部
	if tl, ok := request.Params.Arguments["tail_lines"].(string); ok && tl != "" {
		if n, err := strconv.Atoi(tl); err == nil && n > 0 {
			tailLines = n
		}
	}

	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("打开文件失败: %v", err)), nil
	}
	defer file.Close()

	// 读取文件内容
	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		// 应用过滤器
		if filter == "" || strings.Contains(line, filter) {
			lines = append(lines, line)
		}
	}

	// 处理尾行
	if tailLines > 0 && len(lines) > tailLines {
		lines = lines[len(lines)-tailLines:]
	}

	// 格式化输出
	var result strings.Builder
	result.WriteString(fmt.Sprintf("===== 日志内容 (%s) =====\n", filepath.Base(filePath)))
	if filter != "" {
		result.WriteString(fmt.Sprintf("过滤关键字: %s\n", filter))
	}
	result.WriteString(fmt.Sprintf("总行数: %d\n\n", len(lines)))

	for i, line := range lines {
		result.WriteString(fmt.Sprintf("%d: %s\n", i+1, line))
	}

	return mcp.NewToolResultText(result.String()), nil
}

func logSearchHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	// 获取目录路径
	dirPath, ok := request.Params.Arguments["dir_path"].(string)
	if !ok || dirPath == "" {
		return mcp.NewToolResultError("dir_path 参数必须是非空字符串"), nil
	}

	// 获取搜索关键字
	keyword, ok := request.Params.Arguments["keyword"].(string)
	if !ok || keyword == "" {
		return mcp.NewToolResultError("keyword 参数必须是非空字符串"), nil
	}

	// 获取文件匹配模式
	filePattern, _ := request.Params.Arguments["file_pattern"].(string)
	if filePattern == "" {
		filePattern = "*.log"
	}

	// 格式化输出
	var result strings.Builder
	result.WriteString(fmt.Sprintf("===== 日志搜索结果 =====\n"))
	result.WriteString(fmt.Sprintf("搜索目录: %s\n", dirPath))
	result.WriteString(fmt.Sprintf("关键字: %s\n", keyword))
	result.WriteString(fmt.Sprintf("文件模式: %s\n\n", filePattern))

	// 遍历目录
	matches := 0
	err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 跳过目录
		if info.IsDir() {
			return nil
		}

		// 检查文件名匹配
		matched, err := filepath.Match(filePattern, filepath.Base(path))
		if err != nil || !matched {
			return nil
		}

		// 搜索文件内容
		file, err := os.Open(path)
		if err != nil {
			return nil
		}
		defer file.Close()

		scanner := bufio.NewScanner(file)
		lineNum := 0
		for scanner.Scan() {
			lineNum++
			line := scanner.Text()
			if strings.Contains(line, keyword) {
				matches++
				result.WriteString(fmt.Sprintf("%s:%d: %s\n", filepath.Base(path), lineNum, line))
			}
		}

		return nil
	})

	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("搜索失败: %v", err)), nil
	}

	result.WriteString(fmt.Sprintf("\n找到 %d 个匹配项\n", matches))
	return mcp.NewToolResultText(result.String()), nil
}

func logMonitorHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	// 获取文件路径
	filePath, ok := request.Params.Arguments["file_path"].(string)
	if !ok || filePath == "" {
		return mcp.NewToolResultError("file_path 参数必须是非空字符串"), nil
	}

	// 获取监控持续时间
	duration := "1m"
	if d, ok := request.Params.Arguments["duration"].(string); ok && d != "" {
		duration = d
	}

	// 解析持续时间
	d, err := time.ParseDuration(duration)
	if err != nil {
		return mcp.NewToolResultError("无效的持续时间格式"), nil
	}

	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("打开文件失败: %v", err)), nil
	}
	defer file.Close()

	// 移动到文件末尾
	if _, err := file.Seek(0, io.SeekEnd); err != nil {
		return mcp.NewToolResultError(fmt.Sprintf("定位文件末尾失败: %v", err)), nil
	}

	// 格式化输出
	var result strings.Builder
	result.WriteString(fmt.Sprintf("===== 日志监控 (%s) =====\n", filepath.Base(filePath)))
	result.WriteString(fmt.Sprintf("监控时长: %s\n\n", duration))

	// 开始监控
	start := time.Now()
	reader := bufio.NewReader(file)
	for time.Since(start) < d {
		line, err := reader.ReadString('\n')
		if err != nil {
			if err != io.EOF {
				break
			}
			time.Sleep(100 * time.Millisecond)
			continue
		}

		result.WriteString(fmt.Sprintf("%s %s", time.Now().Format("15:04:05"), line))
	}

	return mcp.NewToolResultText(result.String()), nil
}
